package storage

import (
	"context"
	"fileNest/global"
	"fmt"
	"log"
	"mime/multipart"

	"github.com/minio/minio-go/v7"
)

type DownloadObjectType struct {
	Name   string
	Object *minio.Object
}

// 验证bucket是否存在
func checkBucket(bucketName string) (err error) {
	exists, err := global.Minio.BucketExists(context.Background(), bucketName)
	if err != nil {
		return
	}
	// 不存在即刻创建一个
	if !exists {
		err = global.Minio.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{})
	}
	return
}

// 写入文件
func AddMinioFile(BucketName string, fileHeader *multipart.FileHeader, storagePath string) (err error) {
	file, err := fileHeader.Open()
	if err != nil {
		return
	}
	if err = checkBucket(BucketName); err != nil {
		return
	}
	_, err = global.Minio.PutObject(context.Background(), BucketName, storagePath, file, fileHeader.Size, minio.PutObjectOptions{
		ContentType: fileHeader.Header.Get("Content-Type"),
	})
	return
}

// 从本地上传文件到Minio
func AddMinioFileFromLocal(BucketName, storagePath, mergedFilePath string) (err error) {
	if err = checkBucket(BucketName); err != nil {
		return
	}
	if _, err = global.Minio.FPutObject(context.Background(), BucketName, storagePath, mergedFilePath, minio.PutObjectOptions{}); err != nil {
		return
	}
	return
}

func DeleteOneMinioObject(bucketName, objectUrl string) (err error) {
	err = global.Minio.RemoveObject(context.Background(), bucketName, objectUrl, minio.RemoveObjectOptions{})
	if err != nil {
		return
	}
	return nil
}

// 批量删除Minio文件
func DeleteManyMinioObject(bucketName string, objectUrls []string) (err error) {
	var objectCh = make(chan minio.ObjectInfo)
	go func() {
		defer close(objectCh)
		for _, v := range objectUrls {
			objectCh <- minio.ObjectInfo{Key: v}
		}
	}()
	errCh := global.Minio.RemoveObjects(context.Background(), bucketName, objectCh, minio.RemoveObjectsOptions{})
	flag := false
	for _ = range errCh {
		log.Printf("MinIO 删除失败: %v\n", err)
		flag = true
	}
	if flag {
		err = fmt.Errorf("部分或全部对象删除失败")
	}
	return
}

// 下载Minio文件
func DowmloadMinioObject(bucketName, objectName, localFile string) (obj DownloadObjectType, err error) {
	res, err := global.Minio.GetObject(context.Background(), bucketName, objectName, minio.GetObjectOptions{})
	if err != nil {
		return
	}

	obj.Name = localFile
	obj.Object = res
	return
}
